home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / SAS-C / sc655pch / mount / mount.c next >
Encoding:
C/C++ Source or Header  |  1995-01-23  |  5.9 KB  |  195 lines

  1. /* Copyright (c) 1994 Doug Walker, Raleigh, NC */
  2. /* All Rights Reserved. */
  3.  
  4. #include <dos/dos.h>
  5. #include <exec/memory.h>
  6. #include <exec/execbase.h>
  7. #include <proto/exec.h>
  8. #include <proto/dos.h>
  9.  
  10. #include <string.h>
  11.  
  12. #include "mount.h"
  13.  
  14. #define SysBase (*(struct ExecBase **)4)
  15. #define V37 (SysBase->LibNode.lib_Version > 36)
  16.  
  17. /* Dismount a volume */
  18. /* Note: does not free the memory associated with the volume! */
  19. int DisMount(struct DeviceList *volume)
  20. {
  21.    struct DosInfo *info;
  22.    struct RootNode *root;
  23.    struct DeviceList *tmpdl;
  24.    long *tmpl;
  25.  
  26.    /* Check for any outstanding locks; if present, can't dismount */
  27.    if(volume == NULL || volume->dl_Lock != NULL) return -1;
  28.  
  29.    if(V37)
  30.    {
  31.       RemDosEntry((struct DosList *)volume);
  32.       FreeDosEntry((struct DosList *)volume);
  33.       return 0;
  34.    }
  35.    else
  36.    {
  37.       /* No AmigaDOS 2.0.  Locate the volume on the list and remove it. */
  38.       root   = (struct RootNode   *)DOSBase->dl_Root;
  39.       info   = (struct DosInfo    *)BADDR(root->rn_Info);
  40.       tmpdl  = (struct DeviceList *)BADDR(info->di_DevInfo);
  41.  
  42.       Forbid();
  43.  
  44.       if (volume == tmpdl)
  45.       {
  46.          info->di_DevInfo = volume->dl_Next;
  47.       }
  48.       else
  49.       {
  50.          while (tmpdl != NULL &&
  51.             (struct DeviceList *)(BADDR(tmpdl->dl_Next)) != volume)
  52.          {
  53.             tmpdl = (struct DeviceList *)BADDR(tmpdl->dl_Next);
  54.          }
  55.  
  56.          /* if we found it then take it out of the chain */
  57.          if (tmpdl != NULL)
  58.             tmpdl->dl_Next = volume->dl_Next;
  59.       }
  60.       Permit();
  61.    }
  62.  
  63.    /* We stored the length of the memory block just in front of the volume */
  64.    /* pointer.                                                             */
  65.    tmpl = ((long *)volume)-1;
  66.    FreeMem(tmpl, *tmpl);
  67.  
  68.    return 0;
  69. }
  70.  
  71. /* Mount a volume with the given name; route all handler */
  72. /* messages to the given port.                           */
  73. struct DeviceList *Mount(char *name, struct MsgPort *port)
  74. {
  75.    struct DeviceList *volume;
  76.    struct DosInfo *info;
  77.    struct RootNode *root;
  78.    struct DosList *dlist;
  79.    char work[257];  /* Max BCPL string is 255 + length byte + null terminator */
  80.    int len;
  81.  
  82.    if(name == NULL || port == NULL) return NULL;
  83.  
  84.    if(V37)
  85.    {
  86.       while(1)
  87.       {
  88.          dlist = AttemptLockDosList(LDF_VOLUMES|LDF_WRITE);
  89.          /* Account for DOS bug in V39 which may cause AttemptLockDosList */
  90.          /* to return 1 instead of NULL                                   */
  91.          if(dlist != NULL && dlist != (struct DosList *)1)
  92.             break;
  93.          /* Can't lock the DOS list.  Wait a second and try again. */
  94.          Delay(50);
  95.       }
  96.       volume = (struct DeviceList *)FindDosEntry(dlist, name, LDF_VOLUMES);
  97.       if(volume) RemDosEntry((struct DosList *)volume);
  98.       UnLockDosList(LDF_VOLUMES|LDF_WRITE);
  99.  
  100.       if(!volume && !(volume = (struct DeviceList *)MakeDosEntry(name, DLT_VOLUME)))
  101.       {
  102.          return NULL;
  103.       }
  104.       /* Continued below */
  105.    }
  106.    else  /* Earlier than V37 */
  107.    {
  108.       /* Need to make the name into a BCPL string */
  109.       len = strlen(name);
  110.       if(len > 255) return NULL;
  111.       len += 2;  /* Account for null terminator and BCPL length byte */
  112.       strcpy(work+1, name);
  113.       work[0] = len-2;
  114.       name = work;
  115.  
  116.       root   = (struct RootNode   *)DOSBase->dl_Root;
  117.       info   = (struct DosInfo    *)BADDR(root->rn_Info);
  118.       volume = (struct DeviceList *)BADDR(info->di_DevInfo);
  119.  
  120.       Forbid();
  121.  
  122.       while (volume != NULL)
  123.       {
  124.          if(volume->dl_Type == DLT_VOLUME                           &&
  125.             !memcmp(name, (char *)BADDR(volume->dl_Name), len-1)    &&
  126.             volume->dl_VolumeDate.ds_Days   == 0L                   &&
  127.             volume->dl_VolumeDate.ds_Minute == 0L                   &&
  128.             volume->dl_VolumeDate.ds_Tick   == 0L)
  129.          {
  130.             break;
  131.          }
  132.          volume = (struct DeviceList *)BADDR(volume->dl_Next);
  133.       }
  134.  
  135.       Permit();
  136.  
  137.       /* OK, now did we find it? */
  138.       if (volume == NULL)
  139.       {
  140.          /* No such volume is known to the system, so we will just have to    */
  141.          /* allocate a node to put everything on.  Allocate some extra space  */
  142.          /* after the volume node to hold the name.                           */
  143.          /* This can happen under V37 only, due to the logic above            */
  144.          volume = (struct DeviceList *)AllocMem(sizeof(struct DeviceList)+len+4, 0L);
  145.  
  146.          if(volume == NULL) return NULL;
  147.  
  148.          /* Save the allocated length before the real allocation's start */
  149.          *((long *)volume) = sizeof(struct DeviceList)+len+4;
  150.          volume = (struct DeviceList *)(((char *)volume)+4);
  151.  
  152.          /* We can get to the name by adding 1 to volume, thanks to C's pointer */
  153.          /* arithmetic.                                                         */
  154.          strcpy((char *)(volume + 1), name);
  155.          volume->dl_Name = (BSTR)MKBADDR((volume + 1));
  156.          volume->dl_Type = DLT_VOLUME;
  157.       }
  158.    }
  159.  
  160.    /* Common code between V37 and !V37 */
  161.    /* Give the volume a default date... of course, you can change it later */
  162.    volume->dl_VolumeDate.ds_Days   = 3800L;
  163.    volume->dl_VolumeDate.ds_Minute =
  164.    volume->dl_VolumeDate.ds_Tick   = 0L;
  165.    volume->dl_Lock = NULL;
  166.  
  167.    /* Now we can own the volume by giving it our msgport */
  168.    volume->dl_Task = port;
  169.    volume->dl_DiskType = ID_DOS_DISK;
  170.  
  171.    if(!V37)
  172.    {
  173.       Forbid();
  174.       volume->dl_Next = info->di_DevInfo;
  175.       info->di_DevInfo = MKBADDR(volume);
  176.       Permit();
  177.    }
  178.    else
  179.    {
  180.       while(1)
  181.       {
  182.          dlist = AttemptLockDosList(LDF_VOLUMES|LDF_WRITE);
  183.          /* Account for DOS bug in V39 which may cause AttemptLockDosList */
  184.          /* to return 1 instead of NULL                                   */
  185.          if(dlist != NULL && dlist != (struct DosList *)1)
  186.             break;
  187.          /* Oops, can't lock DOS list.  Wait 1 second and retry. */
  188.          Delay(50);
  189.       }
  190.       AddDosEntry((struct DosList *)volume);
  191.       UnLockDosList(LDF_VOLUMES|LDF_WRITE);
  192.    }
  193.    return volume;
  194. }
  195.